<?php
/**
 * Geneone: Content Management Framework
 * Object Namespace
 *
 * http://geneone.neondragon.net/
 *
 * @package Geneone
 * @author Khlo
 * @version 1.0
 * @copyright 2004-2006 Geneone Development Team
 */
 
require_once 'Gene/Object.php';
 
class Gene_Namespace_Object {
	/**
	 * Calls page in this namespace.
	 *
	 * @static
	 * @var string $id Page ID in Namespace
	 * @var array $action Action Argument String
	 * @return bool Status
	 */
	function call($id, $action=array()) {
		$tpl =& Gene::getTemplate();
		
		/* Check for valid object first */
		if (!Gene_Object::get($id, true)) {
			return false;
		}
		
		/* The default action is "view" */
		if (!isset($action[1]) || !$action[1]) {
			$action[1] = "view";
		}
		
		$actions = Gene_Namespace_Object::getAllowedActions($id);
		if (!isset($actions[$action[1]])) {
			return false;
		}
		
		foreach ($actions as $j => $k) {
			if ($k[0] == $action[1]) {
				$actions[$j][2] = true;
			}
		}
		
		$tpl->assign("actions", $actions);
		
		/* Add additional stylesheets */
		$stylesheets = Gene_Namespace_Object::getStylesheets($id, $action);
		if (count($stylesheets)) {
			foreach ($stylesheets as $i) {
				$tpl->append ("stylesheets", $i);
			}
		}
		
		switch ($action[1]) {
			case 'view':
				return Gene_Namespace_Object::callView($id, $action);
				break;
			case 'edit':
				return Gene_Namespace_Object::callEdit($id, $action);
				break;
			case 'revisions':
				return Gene_Namespace_Object::callRevision($id, $action);
				break;
			case 'new':
				return Gene_Namespace_Object::callNew($id, $action);
				break;
		}
	}
	
	/**
	 * Call View Method
	 * 
	 * @static
	 *
	 * @var string $id Page ID in Namespace
	 * @var array $actions Actions Arguments 
	 *
	 * @return boolean True if the object exists. Otherwise False.
	 */
	function callView($id, $actions=array()) {
		$tpl =& Gene::getTemplate();
		
		if ($obj =& Gene_Object::get($id, true)) {
			$info = $obj->get();
			
			$tpl->append("alternate", array(
				"type" => "application/atom+xml",
				"title" => $info['title'],
				"url" => Gene::xmlLink($obj)
			));
			
			$tpl->assign("curlbase", Gene::makeLink(Gene::objectID($id)));
			
			$view =& $obj->getView();
			$tpl->assign("finalbody", $view->view($actions));
		
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Call Edit Method
	 * 
	 * @static
	 *
	 * @var string $id Page ID in Namespace
	 * @var array $actions Actions Arguments 
	 *
	 * @return boolean True if the object exists. Otherwise False.
	 */
	function callEdit($id, $actions=array()) {
		$tpl =& Gene::getTemplate();
		
		if ($obj =& Gene_Object::get($id, true)) {
			$view =& $obj->getView();
			$tpl->assign ("finalbody", $view->edit($actions));
		
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Call Revision Method
	 * 
	 * @static
	 *
	 * @var string $id Page ID in Namespace
	 * @var array $actions Actions Arguments 
	 *
	 * @return boolean True if the object exists. Otherwise False.
	 */
	function callRevision($id, $actions=array()) {
		$tpl =& Gene::getTemplate();
		
		if ($obj =& Gene_Object::get($id, true)) {
			$info = $obj->get();
			
			// If we have a revision id, show the revision
			$revisionid = Gene_Request::getInteger("revision", GENE_REQUEST_GET);
			if ($revision = $obj->getRevision($revisionid)) {
				// Do we also need to Diff a revision?
				$oldid = Gene_Request::getInteger("oldrevision", GENE_REQUEST_GET);
				if ($oldid AND $oldid != $revisionid AND $oldrevision = $obj->getRevision($oldid)) {
					if ($oldrevision['rev_time'] > $revision['rev_time']) {
						$revision2 = $revision;
						$revision = $oldrevision;
						$oldrevision = $revision2;
					}
					
					
					require_once ("Text/Diff.php");
					$diff = &new Text_Diff(explode("\n", $oldrevision['content']), explode("\n", $revision['content']));
					
					include_once 'Text/Diff/Renderer.php';
					include_once 'Text/Diff/Renderer/inline.php';
					$renderer = &new Text_Diff_Renderer_inline();
					$tpl->assign("diff", $renderer->render($diff));

					$tpl->assign("oldrevision", $oldrevision);
				}

				$tpl->assign("revision", $revision);
			}
			
			$tpl->assign("object", $info);
			$tpl->assign("parents", $obj->getParents());
			$tpl->assign("revisions", $obj->getRevisions());
			$tpl->assign("curlbase", Gene::makeLink(Gene::objectID($id)));
			$tpl->assign("finalbody", $tpl->fetch("objects/revisions"));
			
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Call New Object Method
	 * 
	 * @static
	 *
	 * @var string $id Page ID in Namespace
	 * @var array $actions Actions Arguments 
	 *
	 * @return boolean True if the object exists. Otherwise False.
	 */
	function callNew($id, $actions=array()) {
		/* This doesn't yet support compatible GUIDs */
		$tpl =& Gene::getTemplate();
		$user =& Gene::getUser();
		
		if ($obj =& Gene_Object::get($id, true)) {
			$info = $obj->get();
			
			$objects = array_flip(Gene::getSetting("objects"));
			
			$allowedChilds = $obj->getAllowedChilds();
			
			/* Ensure child type allowed */
			if (count($allowedChilds)) {
				foreach ($allowedChilds as $i) {
					if ($i == "*") {
						$allowedIds = array_values($objects);
					} else {
						if (isset($objects[$i])) {
							$allowedIds[] = $objects[$i];
						}
					}
				}
				
				// Remove any child types current user cannot create
				foreach ($allowedIds as $j => $k) {
					if (!$user->hasPermission("namespaces.object.create.".$k)) {
						unset($allowedIds[$j]);
					}
				}
				
				if (count($allowedIds)) {
					$allowedIds = array_unique($allowedIds);
					
					foreach ($allowedIds as $j => $k) {
						require_once("Gene/Object/Model/".ucfirst($k).".php");
						$obj_class = "Gene_Object_Model_".ucfirst($k);
						
						$p = call_user_func(array($obj_class, "getAllowedParents"));
						
						if (!in_array("*", $p) AND !in_array($obj->getObjectTypeGuid(), $p)) {
							unset($allowedIds[$j]);
						}
					}
					
					$tpl->assign("object", $info);
					$tpl->assign("parents", $obj->getParents());
					$tpl->assign("allowedchilds", $allowedIds);
					$tpl->assign("curlbase", Gene::makeLink(Gene::objectID($id)));
					if (isset($actions[2]) && in_array($actions[2], $allowedIds)) {
						$tpl->assign("newtype", $actions[2]);
						
						$loaddraft = false;

						if ($_SERVER['REQUEST_METHOD'] == "POST") { /* Create new object */
							$title = Gene_Request::getString("objtitle", GENE_REQUEST_POST);
							$desc = Gene_Request::getString("objdesc", GENE_REQUEST_POST);
							$content = Gene_Request::getString("objcontent", GENE_REQUEST_POST);
							$options = array();
		
							// Guest Stuff
							if (!$user->getUserId()) {
								if (Gene::getSetting("object_guest_captcha")) {
									$captchaid = md5(Gene_Request::getString("captchaid", GENE_REQUEST_POST));
									$captchacode = Gene_Request::getString("captchacode", GENE_REQUEST_POST);
									if (isset($_SESSION['captcha_object']) && isset($_SESSION['captcha_object'][$captchaid]) && $_SESSION['captcha_object'][$captchaid] == $captchacode) {
										$captchaerror = false;
									} else {
										$captchaerror = true;
									}
									unset($_SESSION['captcha_object'][$captchaid]);
								}
								
								$options['guest_name'] = Gene_User::canonizePublicName(Gene_Request::getString("guestname", GENE_REQUEST_POST));
								$options['guest_email'] = Gene_Request::getEmail("guestemail", GENE_REQUEST_POST);
								$options['guest_url'] = Gene_Request::getString("guesturl", GENE_REQUEST_POST);
								
								require_once 'Validate.php';
								if (!Validate::uri($options['guest_url'], array("allowed_schemes" => array("http", "https"), "strict" => ""))) {
									unset($options['guest_url']);
								}
								
								if (Gene_Request::getBoolean("guestremember", GENE_REQUEST_POST)) {
									Gene_Request::setCookie("guestname", $options['guest_name']);
									Gene_Request::setCookie("guestemail", $options['guest_email']);
									Gene_Request::setCookie("guesturl", $options['guest_url']);
								} else {
									Gene_Request::setCookie("guestname", "");
									Gene_Request::setCookie("guestemail", "");
									Gene_Request::setCookie("guesturl", "");
								}
							}
							
							$draft = Gene_Request::getBoolean("draft", GENE_REQUEST_POST);
							
							if (isset($captchaerror) && $captchaerror) {
								// Assign stuff
								$tpl->assign("errormsg", "You did not enter the code correctly.");
								$tpl->assign("title", $title);
								$tpl->assign("description", $desc);
								$tpl->assign("edit", array("content" => $content));
							} else if ($draft && $user->getUserId()) {
								require_once ("Gene/Object/View/".ucfirst($actions[2]).".php");
								$classname = "Gene_Object_View_".$actions[2];
								
								$update = Gene_Request::getInteger("draftid", GENE_REQUEST_POST);
								require_once 'Gene/Object/Draft.php';
								if ($update && $draft = Gene_Object_Draft::load($update, $user)) {
									// Check object id, type is correct.
									$info = $obj->get();
									if ($draft['parent_id'] == $info['object_id'] && $draft['type'] == $actions[2]) {
										$draftid = call_user_func(array($classname, "doCreate"), $actions[2], $title, $desc, $content, $obj, $options, $update);
									}
								} else {
									$draftid = call_user_func(array($classname, "doCreate"), $actions[2], $title, $desc, $content, $obj, $options, true);
								}
								
								if (PEAR::isError($draftid)) {
									$tpl->assign("errormsg", $draftid->message);
								} else {
									$tpl->assign("saveddraft", true);
									$loaddraft = $draftid;
								}
							} else {
								require_once ("Gene/Object/View/".ucfirst($actions[2]).".php");
								$classname = "Gene_Object_View_".$actions[2];
								
								$newObjectId = call_user_func(array($classname, "doCreate"), $actions[2], $title, $desc, $content, $obj, $options);
								
								if (!PEAR::isError($newObjectId) && $newObject =& Gene_Object::get($newObjectId)) {
									// Draft to delete?
									$deldraft = Gene_Request::getInteger("draftid", GENE_REQUEST_POST);
									if ($deldraft) {
										require_once 'Gene/Object/Draft.php';
										Gene_Object_Draft::remove($deldraft);
									}
									
									$info = $newObject->get();
									$view =& $newObject->getView();
									
									if ($view->redirectParent) {
										header ("Location: ".Gene::makeLink($info['parent']));
									} else {
										header ("Location: ".Gene::makeLink($info));
									}
									
									exit();
								} else {
									// Assign stuff
									$tpl->assign("errormsg", $newObjectId->message);
									$tpl->assign("title", $title);
									$tpl->assign("description", $desc);
									$tpl->assign("edit", array("content" => $content));
								}
							}
						}
						
						// $loaddraft will exist if draft just saved, otherwise grab draft GET attr
						$draftid = Gene_Request::getInteger("draft", GENE_REQUEST_GET);
						if (!$loaddraft && $draftid) {
							$loaddraft = $draftid;
						}
						
						if ($loaddraft) { // Load Draft
							require_once 'Gene/Object/Draft.php';
							if ($draft = Gene_Object_Draft::load($loaddraft, $user)) {
								// Check object id, type is correct.
								$info = $obj->get();
								if ($draft['parent_id'] == $info['object_id'] && $draft['type'] == $actions[2]) {
									$tpl->assign("draft", $draft);
									$tpl->assign("title", $draft['title']);
									$tpl->assign("description", $draft['description']);
									$tpl->assign("edit", array("content" => $draft['content']));
									$tpl->assign("options", $draft['extra']);
								}
							}
						}
						
						// Display create form
						require_once ("Gene/Object/View/".ucfirst(str_replace(array("/", "\\", "."), "", $actions[2])).".php");
						$tpl->assign("newobjform", call_user_func(array("Gene_Object_View_".ucfirst($actions[2]), "create"), $obj));
					}
					
					$tpl->assign("finalbody", $tpl->fetch("objects/new"));
				} else {
					$tpl->assign("permissionerror", "You cannot create a new object here.");
					$tpl->assign("finalbody", $tpl->fetch("errors/permissionerror"));
				}
			} else {
				$tpl->assign("permissionerror", "You cannot create a new object here.");
				$tpl->assign("finalbody", $tpl->fetch("errors/permissionerror"));
			}
		
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Return allowed actions for Page ID
	 *
	 * @static
	 * @var string $id Page ID in Namespace
	 * @return array Allowed Actions for Page ID
	 */
	function &getAllowedActions($id) {
		$obj =& Gene_Object::get($id, true);
		$auth =& Gene::getAuth();
		$info = $obj->get();
		$user =& Gene::getUser();
		$member = $user->getInfo();
		
		// This caches info on all of the parents of this object so saves shed loads
		// of queries
		$obj->getParents();
		
		$actions = array();
		
		if ($obj->canView()) {
			$actions['view'] = array("view", "View");
		}
		
		if ($obj->canEdit()) {
			$actions['edit'] = array("edit", "Edit");
		}
		
		if ($obj->canRevisions()) {
			$actions['revisions'] = array("revisions", "Revisions");
		}
		
		if ($obj->canWrite()) {
			$actions['new'] = array("new", "New");
		}

		return $actions;
	}
	
	/**
	 * Returns list of required stylesheets
	 *
	 * @static
	 * @var string $id Page ID in Namespace
	 */
	function &getStylesheets($id, $action=array()) {
		if ($action[1] == "revisions") {
			$stylesheets = array("revisions");
		} else {
			$obj =& Gene_Object::get($id, true);
			$info = $obj->get();
			$stylesheets = array($info['type']);
		}
		return $stylesheets;
	}
	
	/**
	 * Exports document as XML.
	 *
	 * @var $id string Page ID
	 *
	 * @return boolean Status
	 */
	function exportXml($id) {
		loadAuth();
		
		if ($obj =& Gene_Object::get($id, true) && $obj->canView()) {
			header ("Content-Type: application/atom+xml");
			
			/* Limit of 5 childs */
			$obj->enablePaging(10);
			$obj->setPageNumber(1);
			
			$info = $obj->get();
			$childs = $obj->getChilds(array("order" => "t_create DESC"));
			
			$tree =& new XML_Tree();

			// <feed> root tag
			$feed =& $tree->addRoot("feed", "", array("xmlns" => "http://www.w3.org/2005/Atom", "xml:base" => Gene::makeLink(Gene::objectId($info))));

			// Add Object Info
			$feed->addChild("title", htmlentities(htmlentities($info['title'])));
			$feed->addChild("subtitle", htmlentities(htmlentities($info['description'])));
			$feed->addChild("link", "", array("href" => Gene::makeLink(Gene::objectId($info))));
			
			if (isset($childs[0])) {
				$feed->addChild("updated", gmdate("Y-m-d\TH:i:s\Z", $childs[0]['t_create']));
			} else {
				$feed->addChild("updated", gmdate("Y-m-d\TH:i:s\Z", $info['t_create']));
			}
			
			$feed->addChild("id", sprintf(Gene::getSetting("guid_uri"), $info['object_id']));
			
			$author =& $feed->addChild("author");
			$author->addChild("name", $info['name']);
			$author->addChild("uri", Gene::makeLink(Gene::userId($info['name'])));
			
			foreach ($childs as $i) {
				if (Gene_Object::checkPermission($i, 'view')) {
					// Add to Item Sequence
					$item =& $feed->addChild("entry", "");
					$item->addChild("title", htmlentities(htmlentities($i['title'])));
					$item->addChild("link", "", array("href" => Gene::makeLink($i)));
					$item->addChild("id", sprintf(Gene::getSetting("guid_uri"), $i['object_id']));
					
					if ($i['t_modify']) {
						$item->addChild("updated", gmdate("Y-m-d\TH:i:s\Z", $i['t_modify']));
					} else {
						$item->addChild("updated", gmdate("Y-m-d\TH:i:s\Z", $i['t_create']));
					}
					
					$item->addChild("published", gmdate("Y-m-d\TH:i:s\Z", $i['t_create']));
					$item->addChild("content", htmlentities($i['content']), array("type" => "html"));
					
					$author =& $item->addChild("author");
					$author->addChild("name", $i['name']);
					$author->addChild("uri", Gene::makeLink(Gene::userId($i['name'])));
				}
			}

			// Display the document
			$tree->dump();
			
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Runs web services.
	 *
	 * @var $method string Method to Call
	 * @return array/bool Result
	 */
	function runWebServices($method) {
		$object = Gene_Request::getInteger("object", GENE_REQUEST_POST);
		loadAuth();
		
		if ($obj =& Gene_Object::get($object, true) && $obj->canView()) {
			$view =& $obj->getView();
			return $view->callWebServices($method);
		}

		return false;
	}
}

?>